package com.zjq.smartdevice.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zjq.smartdevice.dto.UserDto;
import com.zjq.smartdevice.enums.CheckType;
import com.zjq.smartdevice.enums.LoginResutEnum;
import com.zjq.smartdevice.events.MyLoginEvent;
import com.zjq.smartdevice.exception.AddDataErrorException;
import com.zjq.smartdevice.exception.MyErrorCode;
import com.zjq.smartdevice.exception.QueryDataErrorException;
import com.zjq.smartdevice.mapper.SysUserInfoMapper;
import com.zjq.smartdevice.pojo.SysUserInfo;
import com.zjq.smartdevice.service.SysUserInfoService;
import com.zjq.smartdevice.utils.MD5Utils;
import com.zjq.smartdevice.utils.MyStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * @User zhangjiaqi
 * @Project smartdeviceplatgorm
 * @Package com.zjq.smartdevice.service.impl
 * @Date 2022/3/14 19:21
 */
@Service
@Transactional//开启事务的注解
public class SysUserInfoServiceImpl implements SysUserInfoService {

    private ApplicationContext applicationContext;

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    Logger logger = LoggerFactory.getLogger(SysUserInfoServiceImpl.class);

    private SysUserInfoMapper sysUserInfoMapper;

    @Autowired
    public void setSysUserinfoMapper(SysUserInfoMapper sysUserInfoMapper) {
        this.sysUserInfoMapper = sysUserInfoMapper;
    }

    @Override
    public SysUserInfo login(UserDto userDto) {
        //用户传递的账号和密码不能为空
        Assert.isTrue(StringUtils.hasText(userDto.getUsername())&&StringUtils.hasText(userDto.getPassword()),()->{
            throw new QueryDataErrorException("用户名和密码未传递", MyErrorCode.DATA_NULL);
        });

        //根据用户的名字查询用户的数据
        SysUserInfo userInfo = sysUserInfoMapper.findByUsername(userDto.getUsername());
        //查询到了，就获取到盐
        Assert.notNull(userInfo,()->{
            throw new QueryDataErrorException("用户名和密码错误", MyErrorCode.USERNAME_PASSWORD_ERROR);
        });

        String pwdSalt = userInfo.getPwdSalt();
        //用盐将传递过来的密码转成散列值
        //按照之前注册时候规则再次计算散列值
        String pwdMD5 = MD5Utils.getMd5(userDto.getPassword(), pwdSalt, 2048);
        //和刚刚查询到的密码进行比较
        Assert.isTrue(pwdMD5.equalsIgnoreCase(userInfo.getPassword()), () -> {
            //记录日志
            applicationContext.publishEvent(new MyLoginEvent(LoginResutEnum.FAIL, userDto.getUsername()));
            throw new QueryDataErrorException("用户名或者密码错误", MyErrorCode.USERNAME_PASSWORD_ERROR);
        });
        userInfo.setPassword(null);//防止将密码泄露到前端
        userInfo.setPwdSalt(null);//防止将盐泄露到前端
        //记录日志
        applicationContext.publishEvent(new MyLoginEvent(LoginResutEnum.SUCCESS, userDto.getUsername()));
        return userInfo;
    }

    @Override
    public SysUserInfo findById(Long userId) {
        LoggerFactory.getLogger(SysUserInfoServiceImpl.class);
        return sysUserInfoMapper.findById(userId);
    }

    @Override
    public PageInfo<SysUserInfo> findAll(int pageSize, int pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        List<SysUserInfo> userInfoList = sysUserInfoMapper.findAll();
        PageInfo<SysUserInfo> pageInfo = new PageInfo<>(userInfoList);
        return pageInfo;
    }

    @Override
    public void addUser(SysUserInfo sysUserInfo) {
        //数据校验，应该传递的数据必须传递,数据是不是空的，只有数据自己知道

        Assert.isTrue(!sysUserInfo.isEmpty(CheckType.ADD),()-> {
            throw new AddDataErrorException("数据为空", MyErrorCode.DATA_NULL);
        });

        //数据格式的校验
        //手机号校验
        Assert.isTrue(MyStringUtils.check(sysUserInfo.getPhone(),MyStringUtils.mobileRegex),()->{
            throw new AddDataErrorException("手机号格式不正确", MyErrorCode.PHONE_REG_NOT_MACTH);
        });
        //校验邮箱
        Assert.isTrue(MyStringUtils.check(sysUserInfo.getEmail(),MyStringUtils.emailRegex),()->{
            throw new AddDataErrorException("邮箱格式不正确", MyErrorCode.EMAIL_REG_NOT_MACTH);
        });
        //校验唯一的数据
            //用户名，手机号和邮箱必须检查
            //按照用户名查询一下

        SysUserInfo info = sysUserInfoMapper.findByUsername(sysUserInfo.getUsername());
        Assert.isNull(info, () ->{
            throw new AddDataErrorException("用户名已存在", MyErrorCode.USER_ALREADY_EXIST);
        });
        //按照手机号检查
        info = sysUserInfoMapper.findByPhone(sysUserInfo.getPhone());
        Assert.isNull(info, () ->{
            throw new AddDataErrorException("手机号已存在", MyErrorCode.PHONE_ALREADY_EXIST);
        });
        //按照邮箱检查
        info = sysUserInfoMapper.findByEmail(sysUserInfo.getEmail());
        Assert.isNull(info, () ->{
            throw new AddDataErrorException("邮箱已存在", MyErrorCode.EMAIL_ALREADY_EXIST);
        });

        //生成盐
        String salt = MD5Utils.getRandomString(10);
        sysUserInfo.setPwdSalt(salt);
        //生成密码
        String passwordMD5 = MD5Utils.getMd5(sysUserInfo.getPassword(), salt, 2048);//计算密码的md5值
        sysUserInfo.setPassword(passwordMD5);//将密码替换为MD5值
        //设置默认数据
        sysUserInfo.setCreateTime(new Date());
        //检查当前登录的用户，如果是管理员，社设置管理员信息，如果没有用户就是用户自己注册的
        sysUserInfo.setCreateBy(sysUserInfo.getUsername());
        sysUserInfo.setRemark("普通用户");
        //保存到数据库
        sysUserInfoMapper.addUser(sysUserInfo);
        logger.error("添加数据成功");
    }
}
